#include "stdafx.h"
#include "Stream.h"
#include "DetourFunction.h"

FileStream::FileStream( LPCTSTR pszFileName, bool write )
{
	m_pFile = new CFileEx();
	m_pFile->SetThrowErrors(FALSE);
	m_pFile->Open(pszFileName, write?CREATE_ALWAYS:OPEN_EXISTING, write?GENERIC_READ|GENERIC_WRITE:GENERIC_READ);
}

FileStream::~FileStream()
{
	m_pFile->Close();
	delete m_pFile;
}

void FileStream::Flush()
{
	m_pFile->Flush();
}

void FileStream::Close()
{

	m_pFile->Close();
}

//////////////////////////////////////////////////////////////////////////

BinaryStream::BinaryStream(Stream *pStrm)
{
	m_pStrm = pStrm;
}

BinaryStream::~BinaryStream()
{
	Close();
}

void BinaryStream::Write( long lVal )
{
	Write((LPBYTE)&lVal, sizeof(lVal));
}

void BinaryStream::Write( unsigned short usVal )
{
	Write((LPBYTE)&usVal, sizeof(usVal));
}

void BinaryStream::Write( int intVal )
{
	Write((LPBYTE)&intVal, sizeof(intVal));
}

void BinaryStream::Write( const wchar_t *str )
{
	Write((LPBYTE)str, sizeof(wchar_t)*wcslen(str));
}

void BinaryStream::Write( const char *str )
{
	Write((LPBYTE)str, strlen(str));
}

void BinaryStream::Write( const void *ptr, int length )
{
	m_pStrm->Write((LPBYTE)ptr,length);
}

void BinaryStream::Write( char chVal )
{
	Write((LPBYTE)&chVal, sizeof(chVal));
}

void BinaryStream::WriteOne( const DetourVariant *var)
{
	Write((unsigned short)var->type);

	switch(var->type)
	{
	case DetourVariant::INT: Write(var->intVal);break;
	case DetourVariant::LONG: Write(var->lVal);break;
	case DetourVariant::STR: case DetourVariant::PTR:
		Write((unsigned short)var->ptr.len);
		Write(var->ptr.ptr,var->ptr.len);
		break;
	default:
		ASSERT(0);
	}
}


void BinaryStream::WriteAll( const DetourVariant *var )
{
	while(NULL!=var)
	{
		char hasMore = 'M';
		char isLast = 'L';
		if(var->next!=NULL)
			Write(hasMore);
		else
			Write(isLast);
		WriteOne(var);
		var=var->next;
	}
}

long BinaryStream::ReadLong()
{
	long rv = 0;
	Read((LPBYTE)&rv,sizeof(rv));
	return rv;
}

unsigned short BinaryStream::ReadUShort()
{
	unsigned short rv = 0;
	Read((LPBYTE)&rv,sizeof(rv));
	return rv;
}

int BinaryStream::ReadInt()
{
	int rv = 0;
	Read((LPBYTE)&rv,sizeof(rv));
	return rv;
}

std::wstring BinaryStream::ReadWString()
{
	int len = ReadUShort();
	wchar_t *buf = new wchar_t[len+1];
	int cnt = Read((LPBYTE)buf, sizeof(wchar_t)*len);
	buf[cnt]=_T('\0');
	std::wstring str(buf);
	delete buf;
	return str;
}

std::string BinaryStream::ReadString()
{
	int len = ReadUShort();
	char *buf = new char[len+1];
	int cnt = Read((LPBYTE)buf, len);
	buf[cnt]=_T('\0');
	std::string str(buf);
	delete buf;
	return str;
}

int BinaryStream::Read( void *buf, int buflength )
{
	return m_pStrm->Read((LPBYTE)buf,buflength);
}

void BinaryStream::ReadOne( DetourVariant *var )
{
	var->type = ReadUShort();

	switch(var->type)
	{
	case DetourVariant::INT: var->intVal = ReadInt();break;
	case DetourVariant::LONG: var->lVal = ReadLong();break;
	case DetourVariant::STR: case DetourVariant::PTR:
		{
			var->ptr.len = ReadUShort();
			var->ptr.ptr = new char[var->ptr.len];
			Read(var->ptr.ptr,var->ptr.len);
		}
		break;
	default:
		ASSERT(0);
	}	
}

DetourVariant* BinaryStream::ReadAll()
{
	char ch = ReadChar();
	DetourVariant *rv = new DetourVariant();
	DetourVariant *curr = rv;
	ASSERT(ch=='L' || ch=='M');
	for(;;)
	{
		ReadOne(curr);
		if(ch=='L')
			break;
		else if(ch=='M') 
		{
			
			curr->next = new DetourVariant();
			curr=curr->next;
			ch = ReadChar();
		}else{
			ASSERT(FALSE);
			break;
		}
	}
	ASSERT(ch=='L');
	return rv;
}

char BinaryStream::ReadChar()
{
	char ch=0;
	Read((LPBYTE)&ch,sizeof(ch));
	return ch;
}

void BinaryStream::Flush()
{

}

void BinaryStream::Close()
{


}
